
import globals
import gui
from gui import guicol

__author__="Action Farsi"
__date__ ="$24-gen-2009 10.27.53$"

from lev_generator import load_level, generate_level
from entity import *
import ability

import libtcodpy as lt
from copy import copy
import random as rnd

from gui import input_str
import utilities
from types import TupleType
from operator import getitem

import logger
logging = logger.the_log

## TODO separate Game from application
## Game hold info about player, story and levels
class Game:
    def __init__(self):
        self.player = None
        
        self.levels = []
        
        self.comic_age = 0 # Origin
        self.city_name = "Farsopoli"
        
        self.characters = []
        
        self.plot = None
        self.turn = 0

    def new(self):

        ## Create Player Entity

        self.player = Super()
        player = self.player

        player.abilities.append(ability.kungfu)
        player.abilities.append(ability.sharpshooter)
        player.autoset_abilities()
        #player.slots[0].set_ability(player.abilities[0])

        #player.abilities.append(ability.iron_fist)
        #player.abilities.append(ability.sharpshooter)

        #player.slots[0].set_ability(player.abilities[1])
        #player.slots[1].set_ability(player.abilities[0])
        #player.slots[2].set_ability(player.abilities[2])
        player.update_bonus()
        player.add_ent(globals.raws['cola'].get())
        player.add_ent(globals.raws['cape'].get())


        self.levels = [['docks',(23,10),load_level()],
                       ['downtown', (15,42), load_level()]]


        ## Init Level
        globals.c_lev = load_level() #Level()
        lev = globals.c_lev

        # Player
        lev.add_ent(player, pos = globals.c_lev.scr_pts[2])

        # Enemies
        lev.add_ent(globals.raws['thug'].get(),
            pos = globals.c_lev.scr_pts[0])
        lev.add_ent(globals.raws['robber'].get(),
            pos = globals.c_lev.scr_pts[1])
        lev.add_ent(globals.raws['ninja'].get(),
            pos = (4,5))

        # Items
        lev.add_ent(globals.raws['knife'].get(),
            pos = (2,1))
         # Items
        lev.add_ent(globals.raws['cape'].get(),
            pos = (3,1))
             # Items
        lev.add_ent(globals.raws['key'].get(),
            pos = (4,1))
             # Items
        lev.add_ent(globals.raws['cola'].get(),
            pos = (2,1))

        ## Hardcoded quest item
        mc = globals.raws['McGuffin'].get()
        lev.add_ent(mc, pos = (6,6))
        lev.questit = mc

        
    
    def load(self):
        pass
        
    def save(self):
        pass

    def synopsis(self):
        text = "A new superhero arose, he's name is %s"%(player.name)
        return text

class App:
    def __init__(self):
        self.states = []
        self.verb = ""
        self.time = 0
        self.tick = 1
        self.last_tick = 0
        self.tick_beat = 0.7
        
        self.wait_string = False
        self.wait_command = False

    def start(self):
        ## Init Resources
        parse("raws.txt")
        ## TODO streamline init tiles and resources
        
        ## Create or load Game
        globals.game = Game()
        globals.game.new()

        # Short hands
        ## TODO use only one..
        globals.player = globals.game.player
        global player
        player = globals.player
        
        ## Start Game with intro Screen
        self.push_state(IntroState)
        
        
    def timer(self,elaps):
        self.time = self.time + elaps
        if self.time - self.last_tick > self.tick_beat:
            self.tick = -self.tick
            self.last_tick = self.time

    def push_state(self,state):
        self.states.append(state())
        return False ## HACK No-action taken
        
    def pop_state(self):
        self.states.pop().exit()

class GameState:
    def __init__(self):
        self.render_flag = True
        self.is_end_turn = False

        self.wait_command = False
        self.wait_string = False

    def render(self):
        pass
    def action(self,key):
        pass
    def think(self,t):
        pass
    def exit(self):
        pass

class MenuState(GameState):
    def __init__(self,x = 20,y = 40, w= 30,h = 20):
        self.s = 0
        self.title = ""
        self.text = ""
        self.menu = []
        self.x = x
        self.y = y
        self.w = w
        self.h = h

    def render(self):
        #menu_box(self.x,self.y,self.w,self.h,MenuState.menu_list,self.s)
        box = lt.console_new(self.w,self.h)
        lt.console_set_background_color(box, guicol.dialog_bg)
        lt.console_set_foreground_color(box, guicol.dialog_tx)
        lt.console_clear(box)

        row = 1
        if self.title:
            lt.console_print_left(box, 2, row, lt.BKGND_NONE,
                '--'+ self.title+ '----')
            row = row + 2
        if self.text:
            lt.console_print_left_rect(box, 3, row, self.w-6, 10, lt.BKGND_NONE,
                self.text)
            row = row + 10#len(self.text.split("\n"))
        row = row + 1
        if self.menu:
            for i,s in enumerate(self.menu):
                lt.console_print_left(box, 4, row+2*i, lt.BKGND_NONE,
                    '   '+s[0])
                if i == self.s:
                    lt.console_print_left(box,4, row+2*i, lt.BKGND_NONE,
                    '->')

        lt.console_blit(box,0,0,self.w,self.h,0,self.x,self.y,1,1)
        lt.console_delete(box)

    def action(self,key):
        if key.vk == lt.KEY_NONE:
            return -1
        if self.menu == []:
            self.exit()
            return
        
        if key.vk == lt.KEY_ENTER:
            return self.menu[self.s][1]()
        elif key.vk == lt.KEY_ESCAPE:
            return self.exit()
        else:
            self.s = (self.s + keypad(key)[1]) % len(self.menu)
        
        return -1
        
    def exit(self):
        
        return False

class IntroState(MenuState):
    def __init__(self):
        MenuState.__init__(self,15,18)
        self.menu = [('Quick Start', self.newg),
                     ('New Game', lambda :game.push_state(CityMap)),
                     ('Info', self.info),
                     ('Exit',self.exit)]
        self.title = "Main Menu"
        #self.text = "A game of super-heroes\nand super-villanies"
        self.pix = lt.image_load("splash.png")
    
    def render(self):
        ## Splash Screen
        lt.console_clear(0)
        lt.image_blit_2x(self.pix,0,0,0)
        MenuState.render(self)
    
    def newg(self):
        game.states.pop()
        game.states.append(MainState())
        return -1
    
    def info(self):
        print "AF World - v %d"%globals.version
        info = MenuState()
        info.text = "Welcome in AF world\nthe best hero game!\n\n" +\
                    globals.game.synopsis()
        game.states.append(info)
        return 0

    def exit(self):
        MenuState.exit(self)
        game.states.remove(self)
        return False

class HeroCreation(GameState):
    def __init__(self):
        GameState.__init__(self)

        self.name = "Action"
        self.skills = [0,0,0,0,0,0]
        self.max_pt = 10

    def render(self):
        pass
        
        
class CityMap(MenuState):
    def __init__(self):
        MenuState.__init__(self)
        self.city = lt.image_load("resources/city.bmp")
        self.menu = [ (l[0], self.exit) for l in globals.game.levels]

    def render(self):
    
        lt.console_set_background_color(0, guicol.dialog_bg)
        lt.console_set_foreground_color(0, guicol.dialog_tx)

        lt.console_clear(0)
        x,y = 5,0
        
        lt.image_blit_2x(self.city,0,x,y)
        
        lt.console_set_background_color(0, guicol.dialog_bg)
        lt.console_set_foreground_color(0, guicol.dialog_tx)
        
        lt.console_print_left(0, x+4, y+2, lt.BKGND_NONE,
                    ' %s Map '%globals.game.city_name)
                    
        for i,l in enumerate(globals.game.levels):
            lt.console_rect(0, l[1][0]+ x-1, l[1][1]+y-1, len(l[0])+6, 3, True , lt.BKGND_ALPHA(0.8))
            lt.console_print_left(0, l[1][0]+x, l[1][1]+y, lt.BKGND_NONE,
                    '* - ' + l[0])
            if i == self.s:
                lt.console_print_left(0, l[1][0]+x, l[1][1]+y, lt.BKGND_NONE,
                    '0')
            
    
    #def action(self,key):
    #    if key.vk != lt.KEY_NONE:
    #        game.states.pop()
    #    return -1
    
    def exit(self):
        MenuState.exit(self)
        game.states.remove(self)
        return False
        
def sort_scheduler():
    globals.scheduler.sort(key = getitem[0])
        
        
class MainState(GameState):
    def render(self):
        if self.render_flag:
            render()
            self.render_flag = False
        draw_msg_box()

    def action(self,key):
        if game.wait_string:
            c = input_str(key)
            if c is True:
                verbs[game.verb][0](text = globals.input)
                globals.input = ""
                game.wait_string = None
            if c is False:
                globals.input = ""
                game.verb = ""
                game.wait_string = None
            return -1

        self.is_end_turn = action(key)
        if key.vk is not lt.KEY_NONE:
            self.render_flag = True
        return -1

    def think(self,t):
        if self.is_end_turn:
            ## TODO Check on the turn list
            #for entity in globals.c_lev.ents:
            #    entity.click()
            #    entity.think()
            self.update_scheduler()
            #print globals.scheduler
            while True:
                t,e = globals.scheduler.pop(0)
                game.turn = t
                e.last_turn = game.turn
                e.think()
                if e == player: break
                
                
            globals.c_lev.update_walkability()
            self.check_objective()
    
    
    def update_scheduler(self,nturns = 100):
        sched = []
        for entity in globals.c_lev.ents:
            if entity.speed == 0: continue
            lt = entity.last_turn
            for t in xrange(lt+ entity.speed,lt + nturns, entity.speed):
                sched.append( [t,entity] )
        
        sched.sort(key = lambda x:getitem(x,0))
        globals.scheduler = sched
        
    
    def check_objective(self):
        ## TODO create a quest log and condition
        ## Get item
        ## defeat specific enemy
        ## defeat number of enemy
        victory = False
        
        ## Hardcoded victory condition for testing end of level
        qt = globals.c_lev.questit
        if qt in player.inventory:
            logging.info("You got the McGuffin! Victory!!!")
            # Reset victory conditions
            player.drop(qt)
            victory = True
            
        if victory:
            m = MenuState()
            m.menu = [('You win!', m.exit)]
            game.pop_state()
            ## Return to intro state
            game.push_state(IntroState)
            game.states.append(m)
            return
    
    def __init__(self):
        GameState.__init__(self)
        global origin

        #Check if player in level
        if player not in globals.c_lev.ents:
            lev.add_ent(player, pos = globals.c_lev.scr_pts[0])

        self.update_scheduler()
            
        # Center view
        while True:
            d = center_view(player.pos)
            if d == [0,0]:
                break
            origin = origin[0]+d[0],origin[1]+d[1]
            
        logging.info("Entering level")
        
    
class CharacterSheet(GameState):
    def __init__(self):
        GameState.__init__(self)
        text = ["%-20s  (SuperHero)"%(player.name),
        "_______________________________________________________\n",
        "\n".join((" %s   | %s"%l for l in zip(stats_formatter(player.stats),skills_formatter(player.skills)))),
        "","","Slots",
        "_______________________________________________________\n",
        "\n".join((" %-20s : %-20s"%(s.name, s.ability) for s in player.slots)),


        "","","Powers and Abilities",
        "_______________________________________________________\n",
        "\n".join([a.name for a in player.abilities],)
        ]

        x,y,w,h = (4,4,SCREEN[0]-8, SCREEN[1]-8)
        self.box = lt.console_new(w,h)
        lt.console_set_background_color(self.box, guicol.dialog_bg)
        lt.console_set_foreground_color(self.box, guicol.dialog_tx)
        lt.console_clear(self.box)

        lt.console_print_left_rect(self.box, 2, 2, w-4, h-4, lt.BKGND_NONE, "\n".join(text))
        lt.console_blit(self.box,0,0,w,h,0,x,y,1,1)

    def action(self,key):
        if key.vk != lt.KEY_NONE:
            game.states.pop()
        return -1

class InventorySheet(GameState):
    def __init__(self):
        GameState.__init__(self)

        self.verb = ""
        
        self.verbs = {"examine": [self.examine, [] ],
                      "use": [self.use, []],
                 #"wear": (wear.use, (,))
                 }
                 
        self.key_map = {'e': 'examine',
                        'u': 'use'}

        ## TODO Prettify this text
        text = 'Inventory\n----------\n' + '\n'.join(player.inventory_list()) + \
                '\n\n- Actions --\n\n'+'\n'.join([a + ' - ' + b for a,b in self.key_map.items()])
        x,y,w,h = (INV_BOX[0],INV_BOX[1],INV_BOX[2],INV_BOX[3])

        self.box = lt.console_new(w,h)
        lt.console_set_background_color(self.box, guicol.dialog_bg)
        lt.console_set_foreground_color(self.box, guicol.dialog_tx)
        lt.console_clear(self.box)

        lt.console_print_left_rect(self.box, 2, 2, w-4, h-4, lt.BKGND_NONE, text)
        lt.console_blit(self.box,0,0,w,h,0,x,y,1,1)
        

    def render(self):
        draw_msg_box()

    def action(self,key):
        def escape():
            self.verb = ""
            game.verb = ""
            self.wait_command = False
            self.wait_string = False

        if key.vk == lt.KEY_NONE:
            return -1

        if key.vk == lt.KEY_ESCAPE:
            if self.verb == "":
                game.states.pop()
            escape()
            return -1

        if self.wait_command:
            item = char_map[chr(key.c)]
            return self.verbs[self.verb][0] (player.get_item(item))

        if self.verb == "":
            if chr(key.c) in self.key_map.keys():
                v, arg = self.verbs[self.key_map[chr(key.c)]] 
                return (v(*arg))
    
    def examine(self,item = None):
        if item is None:
            self.wait_command = True
            self.verb = "examine"
            logging.info("Examining ")
            return
        if item:
            logging.info("That is a %s"%(item.name))
            self.wait_command = False
            self.verb = ""
            return
            
    def use(self,item = None):
        if item is None:
            self.wait_command = True
            self.verb = "use"
            logging.info("Using ")
            return
        if item:
            if item.is_weapon:
                if player.slots[1].put_item(item):
                    logging.info("You equipped %s"%(item.name))
            #if item.is_armor:
            #    player.slot[].put_item(item)
            
            self.wait_command = False
            self.verb = ""
            return
    

class LookAroundState(GameState):
    def __init__(self):
        GameState.__init__(self)
        self.cursor = player.pos
        
        self.selection = []
        self.s = 0

    def action(self,key):
        if key.vk == lt.KEY_NONE:
            return -1
        p = (self.cursor[0] + keypad(key)[0],
             self.cursor[1] + keypad(key)[1])
        
        if is_on_screen(p):
            if center_view2(p):
                self.render_flag = True
            self.cursor = p
        if key.vk == lt.KEY_ESCAPE:
            self.exit()
            return False
        elif key.c == ord('['):
            self.s = self.s - 1
            return
        elif key.c == ord(']'):
            self.s = self.s +1
            return

        # TODO check is visible
        objects = globals.c_lev.get_entity(pos = self.cursor)

        if key.vk == lt.KEY_ENTER:
            if self.selection:
                logging.info("%s"%objects[self.s % len(self.selection)].description)
            return

        self.s = 0
        self.selection = [e.name for e in objects]
        self.render_flag = True

    def render(self):
        c = 0
        x,y = self.cursor
        dx, dy = delta_screen()
        dx, dy = - (dx + MAP_BOX[0]+1+bord), -(dy + MAP_BOX[1]+1+bord)
        end = t_end()
        
        if self.render_flag:
            draw_map()
            lt.console_blit(map_console, 0, 0, MAP_BOX[2], MAP_BOX[3], 0, MAP_BOX[0], MAP_BOX[1])
            self.render_flag = False
            
        ## color contrast
        back_col = lt.console_get_back(c, dx + x, dy + y)
        if lt.color_get_hsv(back_col)[2] < 0.5:
            lt.console_set_fore(c, dx + x, dy + y,lt.light_grey)
        else:
            lt.console_set_fore(c, dx + x, dy + y,lt.black)
        # Cursor
        lt.console_set_char(c, dx + x, dy + y,'x')

        if self.selection:
            lt.console_set_background_color(c, guicol.dialog_bg)
            lt.console_set_foreground_color(c, guicol.dialog_tx)

            text = "\n"
            length = max([len(e) for e in self.selection])

            row = y + 2 +dx
            lt.console_rect(c, x+2 + dx,row, 4+length, len(self.selection) + 2,
                                True, lt.BKGND_SET)
            row = row+1
            for i,e in enumerate(self.selection):
                lt.console_print_left(c, x+5 + dx,  row, lt.BKGND_NONE, e)
                if i == self.s % len(self.selection):
                    lt.console_put_char(c, x + 3 + dx, row, '@' )
                row = row +1
        
        draw_msg_box()
        
    def exit():
        while True:
            d = center_view(player.pos)
            if d == [0,0]:
                break
            origin = origin[0]+d[0],origin[1]+d[1]
            
        game.pop_state()
        

class Stats(TupleType):
    def __init__(self, stats):
#        self.frc # Force
#        self.cst # Constitution
#        self.ntl # Intelligence
#        self.dxt # Dexterity
#        self.wll # Will
#        self.rfl # Reflex
        self.stats = stats

    def sum(a,b, mask_a = (1,1,1,1,1,1), mask_b = (1,1,1,1,1,1) ):
        total = 0
        for i in xrange(len(mask)):
            total += (a[i] * mask_a[i] + b[i] * mask_b[i])
        return total

def stats_formatter(stats):
        return ["Force         %3d"%stats[0],
        "Constitution  %3d"%stats[1],
        "Intelligence  %3d"%stats[2],
        "Dexterity     %3d"%stats[3],
        "Will          %3d"%stats[4],
        "Reflex        %3d"%stats[5],]

#class Skills(TupleType):
def skills_formatter(skills):
        return["Warrior       %3d"%skills[0],
        "Technologic   %3d"%skills[1],
        "Mutant        %3d"%skills[2],
        "Magic         %3d"%skills[3],
        "Mental        %3d"%skills[4],
        "Cyborg        %3d"%skills[5],]

def change_level():
    game.pop_state()
    game.push_state(MainState)


def keypad(key):
    if key.vk == lt.KEY_UP:
        return (0,-1)
    elif key.vk == lt.KEY_DOWN:
        return ((0,1))
    elif key.vk == lt.KEY_RIGHT:
        return ((1,0))
    elif key.vk == lt.KEY_LEFT:
        return ((-1,0))
    return (0,0)

def center_view(p):
    dx,dy = 0,0
    end = origin[0] + MAP_BOX[2] - 2*bord, origin[1] + MAP_BOX[3]-2*bord
    sx,sy = globals.c_lev.map.size
    scroll =10

    #print "s ", sx,sy
    #print "end", end

    if p[0]-origin[0] < scroll/2:
        dx -= min(origin[0],scroll)
    if p[1]-origin[1] < scroll/2:
        dy -= min(origin[1],scroll)
    if end[0]-p[0] < scroll/2:
        dx += min(sx-end[0],scroll)
    if end[1]-p[1] < scroll/2:
        dy += min(sy-end[1],scroll)

    return [dx,dy]

def center_view2(p):
    global origin
    d = center_view(p)
    origin = origin[0]+d[0],origin[1]+d[1]
    return d[0] == 0 and d[1] == 0
    
def action(key):
    # TODO use keymap
    global finish_loop
    global origin
    ## Movement
    movement = keypad(key)
    if movement != (0,0):
        ## Set movement aid
        if player.move(movement):
            d = center_view(player.pos)
            origin = origin[0]+d[0],origin[1]+d[1]
            return True
        return False

    if key.c is ord('>'):
        print ">"
        if curr_level.map[player.pos[0],player.pos[1]] == '>':
            logging.info("Change level")
            change_level(Level())
            return False
        return False

    ## Exit
    if key.vk == lt.KEY_ESCAPE:
        finish_loop = True
        return False

    ## Attack - fire
    if key.c == ord(' '):
        if player.target:
            player.fire(player.target)

        return True

    #select target
    if key.c == ord('t'):
        for t in player.targets:
            if player.target == None:
                player.target = t
                break
            if player.target == t:
                player.target = None

        return False
    
    if chr(key.c) in key_map.keys():
        v,arg = verbs[key_map[chr(key.c)]] 
        return(v(*arg))

    if key.c == ord('a'):
        n = globals.raws['ninja'].get()
        lev.add_ent(n, pos = (6,4))
        logging.debug("Ninja Added")
        return False

def interact(target = None):
    if target == None or (not isinstance(target,Object)) :
        os = globals.c_lev.get_entity(player.pos, near = 2, exclude = player, filtr = Object)
        if len(os) == 1:
            target = os[0]
        elif len(os) > 1:
            #TODO selection
            target = os[0] #TOCHANGE!!!
        else:
            game.verb = ""
            return False

    target.interact()
    logging.info("Interacted with " + target.name)
    game.verb = ""
    return True

def say(text = None):
    if text:
        logging.info("%s said '%s'"%(player.name, text))
        game.wait_string = False
        game.verb = ""
        return True
    game.wait_string = True
    game.verb = "say"
    return False
    
    
finish_loop = False

messages = []

SCREEN = (64,48)
MAP_BOX = (0,3,SCREEN[0]-24,SCREEN[1]-13)
INV_BOX = (MAP_BOX[2],MAP_BOX[1],SCREEN[0]-MAP_BOX[3],SCREEN[1])#(28,15,40,22)
SID_BOX = (MAP_BOX[2],MAP_BOX[1],SCREEN[0]-MAP_BOX[3],SCREEN[1])

STS_BOX = (0,0,SCREEN[0],MAP_BOX[1])
MSG_BOX = (0,MAP_BOX[3]+STS_BOX[3],MAP_BOX[2],SCREEN[1]-(STS_BOX[3] + MAP_BOX[3]))

msg_console = lt.console_new(MSG_BOX[2],MSG_BOX[3])
sts_console = lt.console_new(STS_BOX[2],STS_BOX[3])
sid_console = lt.console_new(SID_BOX[2],SID_BOX[3])
map_console = lt.console_new(MAP_BOX[2],MAP_BOX[3])

overlay_c = lt.console_new(MAP_BOX[2],MAP_BOX[3])
underlay_c = lt.console_new(MAP_BOX[2],MAP_BOX[3])

lt.console_set_key_color(overlay_c, guicol.alphakey)
lt.console_set_key_color(underlay_c, guicol.alphakey)

def render():
    ## TODO
    ## add specific flag update
    lt.console_set_background_color(None,guicol.bg)
    #lt.console_clear(None)
    ## Map
    draw_map()
    lt.console_blit(map_console, 0, 0, MAP_BOX[2], MAP_BOX[3], 0, MAP_BOX[0], MAP_BOX[1])
    ## TODO
    ## render overlays (cursor, effects, time dependent animation)
    draw_overlay()
    #draw_underlay()
    #lt.console_blit(underlay_c, 0, 0, MAP_BOX[2], MAP_BOX[3], 0, MAP_BOX[0], MAP_BOX[1],1,0)
    lt.console_blit(overlay_c, 0, 0, MAP_BOX[2], MAP_BOX[3], 0, MAP_BOX[0], MAP_BOX[1],1,0)
    
    ## Status and GUI
    lt.console_blit(draw_sts_box(), 0, 0, STS_BOX[2], STS_BOX[3], 0, STS_BOX[0], STS_BOX[1])
    lt.console_blit(sid_console, 0, 0, SID_BOX[2], SID_BOX[3], 0, SID_BOX[0], SID_BOX[1])
    

def modal_box(x,y,w,h, text, callback = None):
    box = lt.console_new(w,h)
    lt.console_set_background_color(box, guicol.dialog_bg)
    lt.console_set_foreground_color(box, guicol.dialog_tx)
    lt.console_clear(box)

    lt.console_print_left_rect(box, 2, 2, w-4, h-4, lt.BKGND_NONE, text)
    lt.console_blit(box,0,0,w,h,0,x,y,1,1)
    lt.console_flush()
    logging.debug("Modal Box")
    ## TODO Set a good loop
    while True:
        lt.sys_sleep_milli(50)
        key = lt.console_check_for_keypress(lt.KEY_RELEASED)
        if callback and key:
            return callback(key)
        else:
            return

def menu_box(x,y,w,h, menu_list,sel):
    box = lt.console_new(w,h)
    lt.console_set_background_color(box, guicol.dialog_bg)
    lt.console_set_foreground_color(box, guicol.dialog_tx)
    lt.console_clear(box)

    lt.console_set_foreground_color(0, guicol.tx)
    for i,s in enumerate(menu_list):
         lt.console_print_left(box, 4, 3+2*i, lt.BKGND_NONE,
             '   '+s)
         if i == sel:
             lt.console_print_left(box,4, 3+2*i, lt.BKGND_NONE,
             '->')

    lt.console_blit(box,0,0,w,h,0,x,y,1,1)

origin = [0,0]
bord = 1
t_end = lambda :(origin[0] + MAP_BOX[2] - 2*bord, origin[1] + MAP_BOX[3]-2*bord)


def is_on_screen(p):
    end = t_end()
    return (p[0] >= origin[0] and p[0] < end[0] \
        and p[1] >= origin[1] and p[1] < end[1])

def delta_screen():
    return origin[0]-bord,origin[1]-bord
    
def draw_map():
    tmap = globals.c_lev.tmap
    
    c = map_console

    # TODO Scroll
    dx, dy = delta_screen()
    
    end = t_end()

    lt.map_compute_fov(tmap, player.pos[0], player.pos[1], 10, True, lt.FOV_BASIC)

    #TODO set mapcolor from tiles
    lt.console_set_background_color(c, lt.Color(10,10,10))
    lt.console_rect(c, 0, 0, MAP_BOX[2], MAP_BOX[3], True, lt.BKGND_SET)
    lt.console_set_foreground_color(c,lt.black)

    for j in xrange(max(0,origin[1]),min(globals.c_lev.map.size[1], end[1])):
        for i in xrange(max(0,origin[0]),min(globals.c_lev.map.size[0], end[0])):
            t = globals.tiles[ globals.c_lev.map[i,j]]
            lt.console_set_back(c, i-dx, j-dy, t.bg, lt.BKGND_SET)
            if not lt.map_is_in_fov(tmap, i, j):
                lt.console_set_back(c, i-dx, j-dy, lt.dark_grey, lt.BKGND_MULTIPLY)
            #if globals.c_lev.map[i,j] == '.':
            #    lt.console_set_back(c, i-dx, j-dy, lt.black, lt.BKGND_SET)
            lt.console_put_char(c, i-dx, j-dy, t.symb, lt.BKGND_NONE)

    #draw Entities
    # TODO Order items_first
    for entity in [ e for e in globals.c_lev.ents if e.owner == globals.c_lev]:
        if not is_on_screen(entity.pos):
            continue
        if lt.map_is_in_fov(tmap, entity.pos[0], entity.pos[1]):
            lt.console_set_fore(c, entity.pos[0]-dx, entity.pos[1]-dy, entity.color)
            lt.console_set_char(c, entity.pos[0]-dx, entity.pos[1]-dy, entity.symbol)

    #identify current target
    if player.target:
        lt.console_set_back(c, player.target.pos[0]-dx, player.target.pos[1]-dy, guicol.marker, lt.BKGND_SET)

    #draw player as last
    if is_on_screen(player.pos):
        lt.console_put_char(c, player.pos[0]-dx, player.pos[1]-dy, player.symbol, lt.BKGND_NONE)

def console_progress_bar(console, x,y, value, size = 15,
                            mins = 0, maxs = 100, color1 = lt.dark_red, color2 = lt.red):
    lt.console_set_background_color(console,color1)
    lt.console_rect(console, x, y, size, 1, True, lt.BKGND_SET)
    lt.console_set_background_color(console,color2)
    lt.console_rect(console, x, y, int(max((size * value / (maxs - mins),1))), 1, True, lt.BKGND_SET)

def draw_sts_box():
    lt.console_set_background_color(sts_console, guicol.sts_bg)
    lt.console_set_foreground_color(sts_console, guicol.tx)
    lt.console_clear(sts_console)
    #lt.console_print_frame(sts_console, 0, 0, STS_BOX[2], STS_BOX[3], True, "Status")
    lt.console_print_left_rect(sts_console, 2, 1, STS_BOX[2]-2, STS_BOX[3]-2, lt.BKGND_NONE,
        "%-15s %s %5d/100 HP  -  %-15s"%(player.name, repr(player.stats), player.life, player.curr_item))


    lt.console_set_background_color(sid_console, guicol.bg)
    lt.console_set_foreground_color(sid_console, guicol.tx)
    lt.console_clear(sid_console)

    row = 2
    # Current ability and keys
    lt.console_print_left(sid_console, 2, row, lt.BKGND_NONE, '__ ABILITIES _____')
    row +=2
    for i,s in enumerate(player.slots):
        lt.console_print_left(sid_console, 2, row, lt.BKGND_NONE, "%d - "%(i+1) + s.ability.name)
        row += 1
    lt.console_set_fore(sid_console, 2, row+2, guicol.marker)
    
    row = row + 6
    # Enemy Statistics on HUD
    lt.console_print_left(sid_console, 2, row, lt.BKGND_NONE, '__ TARGETS _______')
    row = row + 2
    for i,e in enumerate(player.targets):
        console_progress_bar(sid_console, 4,row +2*i, e.life, maxs = e.maxlife)
        lt.console_print_left(sid_console, 5, row + 2*i, lt.BKGND_NONE, e.name)
        if player.target == e:
            lt.console_set_fore(sid_console, 2, row + 2*i, guicol.marker)
            lt.console_set_char(sid_console, 2, row + 2*i, '@')

    if game.str_input != 0:
        lt.console_print_left(sts_console, 2, STS_BOX[3]-2, False, ":%s_"%game.str_input)
    return sts_console

def draw_msg_box():
    lt.console_clear(msg_console)
    lt.console_print_frame(msg_console, 0, 0, MSG_BOX[2], MSG_BOX[3], False,lt.BKGND_NONE, "Messages")
    log = '\n'.join(logger.messages[MSG_BOX[3]-5:])
    lt.console_print_left_rect(msg_console, 2, 2, MSG_BOX[2]-2, MSG_BOX[3]-5, lt.BKGND_SET, log)
    if game.tick == 1:
        caret = ' '
    else:
        caret = '_'
    lt.console_print_left(msg_console, 2, MSG_BOX[3]-2, lt.BKGND_SET, 'Command: '+ game.verb + ' ' + globals.input + caret)

    # FPS
    if True:
        lt.console_print_left(msg_console, MSG_BOX[2]-10, 0, lt.BKGND_SET,'FPS %4.d'%lt.sys_get_fps())

    lt.console_blit(msg_console, 0, 0, MSG_BOX[2], MSG_BOX[3], 0, MSG_BOX[0], MSG_BOX[1])

def console_blit_f(src,xSrc,ySrc,wSrc,hSrc,dst,xDst,yDst):
    for x,y in xyiter(wSrc,hSrc):
        lt.console_set_fore(dst,x+xDst,y+yDst, lt.get_fore(src,x+xSrc, y+ySrc))
        lt.console_set_char(dst,x+xDst,y+yDst, lt.get_char(src,x+xSrc, y+ySrc))
        
def console_blit_b(src,xSrc,ySrc,wSrc,hSrc,dst,xDst,yDst, flag):
    for x,y in xyiter(wSrc,hSrc):
        lt.console_set_back(dst,x+xDst,y+yDst, lt.get_back(src,x+xSrc, y+ySrc) , flag)
        #lt.console_set_char(dst,x+xDst,y+yDst, lt.get_char(src,x+xSrc, y+ySrc))
        
def color_equals(a,b):        
    return a.r == b.r and a.g == b.g and a.b == b.b

def console_blit_o(src,xSrc,ySrc,wSrc,hSrc,dst,xDst,yDst, alphac = lt.black, flag = lt.BKGND_NONE):
    for x,y in xyiter((wSrc,hSrc)):
        c = lt.console_get_back(src,x+xSrc, y+ySrc)
        if not color_equals(c,alphac):
            lt.console_set_back(dst,x+xDst,y+yDst, c , flag)
            
        c = lt.console_get_char(src,x+xSrc, y+ySrc)
        
        if c != 32:
            lt.console_set_fore(dst,x+xDst,y+yDst, lt.console_get_fore(src,x+xSrc, y+ySrc))
            lt.console_set_char(dst,x+xDst,y+yDst, lt.console_get_char(src,x+xSrc, y+ySrc))
    
def draw_overlay():
    c = overlay_c
    lt.console_set_background_color(c, lt.black)
    lt.console_clear(c)
    lt.console_print_left(c,10,10,lt.BKGND_NONE,"pippopopopo")
    dx, dy = delta_screen()
        
def draw_underlay():
    c = underlay_c
    #lt.console_set_background_color(c, guicol.alphakey)
    #lt.console_clear(c)
    #c = map_console
    dx, dy = delta_screen()
    #identify current target
    if player.target:
        lt.console_set_back(c, player.target.pos[0]-dx, player.target.pos[1]-dy, guicol.marker, lt.BKGND_SET)
    
def use_slot(n):
    return player.use_slot(player.get_slot(n),player.target)

player = None
game = App()
game.str_input = 0           
    
c_target = lambda: player.target()

verbs = {"say": [say,[]],
         "inventory": [game.push_state, [InventorySheet,]],
         "character": [game.push_state, [CharacterSheet,]],
         "get": [lambda: player.pick_up(), []],
         "drop": [lambda: player.drop(), []],
         "interact" : [interact, [c_target]],
         "slot1": [use_slot, [0] ],
         "slot2": [use_slot, [1] ],
         "look": [game.push_state, [LookAroundState,]],
         "reset": [change_level, []] }

key_map = {'s': 'say',
           'u': 'interact',
           'i': 'inventory',
           'c': 'character',
           'g': 'get',
           'd': 'drop',
           '1': 'slot1',
           '2': 'slot2',
           'l': 'look',
           'q': 'reset'}



if __name__ == "__main__":
    print "AfWorld"
    logging.debug("Init game")
    ## Initializations
    lt.console_init_root(SCREEN[0], SCREEN[1], 'AfW',False)
    #libtcod.console_set_keyboard_repeat(10, 10)
    render_flag = True
    
    game.start()
    
    ## Main loop
    while (not lt.console_is_window_closed() and not finish_loop):
    ## TODO Loop on modal frames
        ## Logic
        game.timer(lt.sys_get_last_frame_length())
        game.states[-1].think(1)
        
        ## Render
        game.states[-1].render()
        lt.console_flush()
        
        ## Input
        # key
        key = lt.console_check_for_keypress(True)
        # TODO Mouse
        # TODO Text input
        game.states[-1].action(key)
        
        # exit if there are no states in game
        if game.states == []:
            break

    ## Destroy
    lt.console_delete(msg_console)
    lt.console_delete(sts_console)

